import hashlib
import os
from io import BytesIO

from apps.blueprints.article.models import Articles
from apps.blueprints.user.models import User
from exts import db, generate_imagecode
from flask import (flash, g, jsonify, make_response, redirect, render_template,
                   request, session, url_for)
from flask_login import login_required, login_user, logout_user
from settings import Config
from sqlalchemy import and_, not_, or_
from werkzeug.security import check_password_hash, generate_password_hash
from werkzeug.utils import secure_filename

from . import user_bp
from .form import UserLoginForm

required_login_list = ['/center','/register','/change'] # 主要验证路由的列表

ALLOWED_EXTENSIONS = set(['png', 'jpg', 'jpeg','bmp','gif']) # 上传的头像允许的扩展名

@user_bp.before_app_request # 钩子函数，在请求之前执行
def first_request():
    # print(f'first_request:{request.path}')
    if request.path in required_login_list:
        id = session.get('uid', None)
        if not id:
            return render_template('user/login.html')
        else:
            user = User.query.get(id)
            g.user = user # g对象，是本次请求的对象
            # return render_template('user/login.html')

@user_bp.after_app_request # 钩子函数，在请求之后执行
def after_request(response):
    # print(f'after_request:{request.path}')
    # response.set_cookie('a','bbb',max_age=3600) # 特殊处理，一般不需要
    return response

@user_bp.teardown_app_request
def teardown_request(response):
    # print(f'teardown_request:{request.path}')
    # return render_template('user/index.html')
    return response
@user_bp.route('/') # 用户中心
def index():
    # 1.cookie的获取方式
    # uid = request.cookies.get('uid', None) # 获取cookie中的uid, uid和登录页面设置的key是一致的
    
    # 2.session的获取方式
    uid = session.get('uid', None)
    if uid:
        user = User.query.get(uid) # 根据uid查询用户信息
        return render_template('user/index.html',user=user)
    else:
        # 无用户，请登录
        return render_template('user/index.html')

@user_bp.route('/register',methods=['GET','POST']) # 用户注册
def register():
    if request.method == 'POST':
        username = request.form.get('username')
        password = request.form.get('password')
        repassword = request.form.get('repassword')
        phone = request.form.get('phone')
        email = request.form.get('email')
       
        if password == repassword:
            # 注册用户，结合user模型，把注册的用户写入数据库
            # session['username'] = username
            
            # 注册用户
            user = User()
            user.username = username
            user.password = generate_password_hash(password)
            user.phone = phone
            user.email = email
            
            # print(f"用户名:{username},密码:{password},手机号:{phone}:邮箱:{email}")
            
            db.session.add(user)
            db.session.commit()
            
            return redirect(url_for('user.index'))
            
            # # 查询数据库 和 注册提交的用户名比较
            # userDb = User.query.filter_by(username=username).first()
            # if userDb: # 用户是存在的
            #     if userDb.username != username:
            #         # 添加数据和提交数据到数据库                    
                    
            #         # 注册成功后跳转到首页
            #         return redirect(url_for('user.user_center', users=user))
            #     else:
            #         return "用户名已存在"
            #         return render_template('register.html', msg='用户名已存在')
            # else: # 注册的用户不在数据库中则注册用户到数据库中
            #     db.session.add(user)
            #     db.session.commit()
            #     return redirect(url_for('user.user_center', users=user))  
        else:
            flash('两次密码不一致')
            return render_template('user/register.html')
    return render_template('user/register.html')

@user_bp.route('/login',methods=['GET','POST']) # 登录
def login():
    if request.method == 'POST':
        fcode = request.args.get('fcode')
        print(fcode)
        if fcode == '1': # 用户名和密码登录
            username = request.form.get('username')
            password = request.form.get('password')
            
            # 查询数据库,用户名是唯一的，所以只查询一条数据
            user = User.query.filter(User.username == username).first() 
            if user: 
                if check_password_hash(user.password, password):
                    # 方式1： 以下是cookie实现机制    
                    # response对象如下
                    # response = redirect(url_for('user.index'))
                    # response = render_template(xxx)
                    # response = Response()
                    # response = make_response()
                    # response = jsonify()                
                    # response = redirect(url_for('user.index'))                
                    # response.set_cookie('uid', str(user.id), max_age=3600) # 设置cookie，有效期是3600秒，即1小时
                    
                    # 方式2：session实现机制
                    session['uid'] = user.id
                    response = redirect(url_for('user.index'))

                    return response
                else:
                    return render_template('user/login.html',msg='用户名或者密码有误!')
            else:
                return render_template('user/login.html',msg='用户不存在!')
        else: # 手机号和验证码登录
            phone = request.form.get('phone')
            code = request.form.get('code')
            return render_template('user/login.html')
    return render_template('user/login.html')

@user_bp.route('/logout') # 退出登录
def logout():
    response = redirect(url_for('user.index'))
    response.delete_cookie('uid') # 删除cookie
    session.clear() # 删除session的内存空间和删除cookie
    # del session['uid'] # 只会删除session的这个键值对不会删除session空间和cookie
    return redirect(url_for('user.index'))

@user_bp.route('/center') # 用户中心
def user_center():  
    return render_template('user/center.html',user = g.user)

@user_bp.route('/change',methods=['GET','POST']) # 用户信息修改
def user_change():
    if request.method == 'POST':
        username = request.form.get('username')
        phone = request.form.get('phone')
        email = request.form.get('email')
        # 只要是文件图片，获取方式必须使用request.files.get('icon')
        icon = request.files.get('icon') # icon对应的方法如下 filestore对象
        icon_name = icon.filename # 获取上传的文件名
        
        
        # 查询一下手机号码
        # users = User.query.all()
        # for user in users:
        #     if user.phone == phone:
        #         # 已经有人注册了此号码，不能修改，返回到用户中心页面
        #         # 或者在html页面添加ajax发送请求校验手机号是否已经使用
        #         return render_template('user/center.html',user = g.user,msg='手机号码已存在')

        suffix = icon_name.rsplit('.')[-1]
        if suffix in ALLOWED_EXTENSIONS:
            # 保证文件名是符合python的命名规则
            icon_name = secure_filename(icon_name) 
            
            # print(f"用户名:{username},手机号:{phone},邮箱:{email},icon:{icon_name}")
            
            # 文件的path路径
            file_path = os.path.join(Config.UPLOAD_ICON_DIR,icon_name)
            icon.save(file_path) # 保存成功
            
            user =g.user
            user.username = username
            user.phone = phone
            user.email = email
            path = 'upload/icon/'
            user.icon = os.path.join(path,icon_name)
            # print(user.icon)
            db.session.commit()
        
            return redirect(url_for('user.user_center'))
        else:
            # 上传的文件不是图片格式的，不保存到指定的路径
            return render_template('user/center.html',user = g.user,msg='上传的文件不是图片格式的')        
    else:
        render_template('user/center.html',user = g.user)


@user_bp.route('/search')  # 主页面的搜索操作
def search(): 
    keyword = request.args.get('search_value') # 用户名或者是手机号码
    # 写查询语句  模糊查询
    user_list = User.query.filter(or_(User.username.contains(keyword), User.phone.contains(keyword))).all()
    # print(user_list)
    return render_template('user/center.html', users=user_list)

# 校验用户是否存在，不存在则提示到页面中
@user_bp.route('/check_username',methods=['GET','POST'])
def check_username():
    uid = request.args.get('uid')
    user = User.query.filter(User.username == uid).first()
    if user is None:
        return jsonify({'code': 400, 'msg': '此用户未注册,请注册'})
    else:
        return jsonify({'code': 200,'msg': '此用户已注册'})
    
# 手机号码验证
@user_bp.route('/check_phone',methods=['GET','POST'])
def check_phone():
    phone = request.args.get('phone')
    user = User.query.filter(User.phone == phone).first()
    if user:
        return jsonify({'code': 400, 'msg': '此号码已被注册'})
    else:
        return jsonify({'code': 200, 'msg': '此号码可以注册'})

@user_bp.route('/send_message',methods=['GET','POST']) # 发送手机短信验证码
def send_message():
    phone = request.args.get('phone')
    print(f'手机号码：{phone}')
    
    if 1: # 手机号码发送成功
        pass
        session[phone] = '123456'
        return jsonify({'code': 200,'msg': '发送成功'})
    else:
        return jsonify({'code': 400,'msg': '发送失败'})

@user_bp.route('/delete',endpoint='delete') # 删除用户
def user_delete(): # 删除用户
    id = request.args.get('id') # 获取用户id，主键
    user = User.query.get(id) # 获取该id的用户信息 
    
    # 方式1：逻辑删除
    user.isdelete = True # 逻辑上删除，设为True就是代表删除
    db.session.commit() # 提交数据到数据库
    
    # 2.物理删除，数据库中的数据删除
    # db.session.delete(user)
    # db.session.commit()
    
    return redirect(url_for('user.user_center'))


@user_bp.route('/publish', methods=['GET', 'POST']) # 发布文章
def publish_article():
    if request.method == 'POST':
        title = request.form.get('title') # 文章标题
        content = request.form.get('content') # 文章内容
        uid = request.form.get('uid') # 用户ID
        
        # 添加文章到数据库
        article = Articles(title=title, content=content,user_id=uid) # 
        db.session.add(article)
        db.session.commit()
        return redirect(url_for('article.add_article'))
    else:
        users = User.query.filter(User.isdelete == False).all()
        return render_template('article/add_article.html', users=users)

# form表单在HTML中的使用
@user_bp.route('/form', methods=['GET', 'POST']) # 表单
def user_form():
    userloginform = UserLoginForm()
    if userloginform.validate_on_submit(): # 执行UserLoginForm中的所有校验方法
        username = userloginform.username.data # 获取用户名
        password = userloginform.password.data
        phone = userloginform.phone.data
        recaptcha = userloginform.recaptcha.data
        
        # 获取上传的文件
        icon = userloginform.icon.data # FileStorage对象
        filename = secure_filename(icon.filename)
        BASE_DIR = os.path.dirname(os.path.abspath(__file__)) # 获取当前文件的绝对路径
        UPLOAD_DIR = Config.UPLOAD_ICON_DIR
        filepath = os.path.join(UPLOAD_DIR, filename)
        # print(filepath)
        # print(filename)
        icon.save(filepath) # 保存到本地路径
        
        return '提交成功'
    return render_template('user/form.html',loginform=userloginform)

@user_bp.route('/get_imagecode') # 请求验证码
def get_image():
    # 调用图片验证码函数
    img, code = generate_imagecode()
    
    # code存入在session中
    session['code'] = code
    
    buffer = BytesIO() # 将image对象转换成二进制
    img.save(buffer, 'JPEG') # 保存到缓存中
    buf_bytes = buffer.getvalue()
    
    response = make_response(buf_bytes)
    response.headers['Content-Type'] = 'image/jpeg' # 设置响应头
    
    return response
 
# form和bootstrap结合使用的例子
@user_bp.route('/bootform', methods=['GET', 'POST'])
def boot_form_user():
    userloginform = UserLoginForm()
    return render_template('user/boot_form.html',loginform=userloginform)

# 闪现的使用
@user_bp.route('/flash',methods=['GET','POST'])
def user_flash():
    if request.method == 'POST':
        # 验证是否是admin用户
        username = request.form.get('username')
        print(f'用户名:{username}')
        if username == 'admin':
            flash('登录成功')
            flash('哈哈')
            flash('我是测试flash')
        else:
            flash('不是amdin，登录失败','error')
            flash('哈哈，你不是admin','warning')
            flash('我在测试flash','info')
            # app.logger.debug('我是测试flash')
        
        return render_template('user/flash.html')
        
    # flash('这是一条闪现的消息')
    return render_template('user/flash.html')

# ------------------------------分割线---------------------------
@user_bp.route("/select")
def user_select(): # 用户查询
    user = User.query.get(1) # 根据主键来查询用户数据
    user = User.query.filter(User.username == 'admin').first() # filter使用的比较多，根据条件查询数据
    
    # user = User.query.filter(User.username.startswith('y')).all() # 查询以y开头的所有数据
    
    # user = User.query.filter(User.username.endswith('y')).all() # 以y结尾
    user_list = User.query.filter(User.username.contains('y')).all() # 包含
    # user = User.query.filter(User.username.like('%y%')).all() # 模糊查询
    user_list = User.query.filter(or_(User.username=='yl837'), (User.password=='123')).all() # 多条件查询
    user_list = User.query.filter(and_(User.username=='yl837'), (User.password=='123')).all()
    user_list = User.query.filter(not_(User.username=='yl837')).all()
    
    user_list = User.query.order_by(User.id.desc()).all() # 降序排序
    user_list = User.query.order_by(User.id.asc()).all() # 升序排序
    user_list = User.query.order_by(User.rdatetime.desc()).all() # 时间降序
    user_list = User.query.order_by(User.rdatetime.asc()).all() # 时间升序
    
    # limit的是要 + offset的值   分页查询
    user_list = User.query.limit(2).all() # 获取钱2条
    user_list = User.query.offset(4).limit(10).all() # 跳过4条，获取10条
    print(user_list)
    
    return render_template('user/select.html',users=user_list)